#include "Numeric.h"

using namespace std;


void matrixOperationsTest() {	//matrix operations test functions
	Matrix A(2,2);
	Matrix B(2,2);
	Matrix C(2,2);
	Matrix D(2,3);//tranpose
	Matrix F(3,2);//transpose test

	A(0,0)=2; A(0,1)=1;
	A(1,0)=1; A(1,1)=3;

	B(0,0)=1; B(0,1)=2;
	B(1,0)=2; B(1,1)=1;

	D(0,0)=1; D(0,1)=1; D(0,2)=1;
	D(1,0)=2; D(1,1)=2; D(1,2)=2;

	cout << "Matrix Operations: "  << endl;

	C = A * 3;		//test matrix scalar multiplication
	cout << "Scalar Multiplication "<< C  << endl;
	C = A * B;		//test matrix multiplication
	cout << "Matrix Multiplicaiton "<< C  << endl;
	C = A + B;		//test matrix addition
	cout << "Matrix Addition "<< C  << endl;
	C = A - B;		// test matrix subtraction
	cout << "Matrix Subtraction " << C  << endl;
	C = B.inv(B);	// test matrix inversion
	cout << "Matrix Inverstion "<< C  << endl;
	C = C.identity(3);// contructs identity matrix 
	cout << "Matrix to be Transposed "<< D << endl;//matrix to be tranposed
	F = D.tranpose(D);
	cout << "Transposed Matrix "<< F << endl;//transposed matrix
	cout << "Scalar Divsion "<< A/2 << endl;// test matrix/scalar division
	cout << "Matrix/Matrix Division "<< A/B << endl;// test matrix/matrix division
	cout << "Guass Jordan "<< 1.0/A << endl;//test gauss jordan divsion matrix by scalar int 
}
void normTest(){

	Matrix A(2,3);

	A(0,0) = 1; A(0,1) = 2; A(0,2) = 3; 
	A(1,0) = 4; A(1,1) = 50; A(1,2) = 6;

	vector<double> testVector;
	for (int i = 0; i < 5; i++) testVector.push_back(i);

	double negValue = -3819.3431348;
	cout << "Norm Test: "  << endl;

	cout << "Matrix Norm "<< norm(A) << endl;//test martrix norm
	cout << "Vector Norm "<< norm(testVector)  << endl;//test vector norm
	cout << "Double Norm " << norm(negValue) << endl;//test doulbe norm
}
void symmetricZeroTest(){
	Matrix A(3,3);//symmetric matrix
	Matrix B(3,3);//non symmetric matrix

	A(0,0)=1; A(0,1)=7; A(0,2)=3;
	A(1,0)=7; A(1,1)=4; A(1,2)=-5;
	A(2,0)=3; A(2,1)=-5; A(2,2)=6;

	B(0,0)=1; B(0,1)=7; B(0,2)=6;
	B(1,0)=7; B(1,1)=4; B(1,2)=-55;
	B(2,0)=3; B(2,1)=-5; B(2,2)=6;

	cout << "Is Almost Symmetric: "  << endl;
	//symmetric test
	//should return true "1"
	cout << "Symmetric Matrix " << is_almost_symmetric(A) << endl;
	//should return false "0"
	cout << "Non Symmetric Matrix "<< is_almost_symmetric(B) << endl;

	cout << "Is Almost Zero: "  << endl;
	//zero test
	//should return true "1"
	cout << "Almost Zero "<< is_almost_zero(A) << endl;
	//should return false "0"
	cout << "Not Almost Zero "<< is_almost_zero(B) << endl;	
}

void conditionNumTest() {
	Matrix A(2,2);

	A(0,0)=2; A(0,1)=1;
	A(1,0)=1; A(1,1)=3;

	Condition_Number test;
	//matrix condition number
	cout << "Conditon Number: "  << endl;
	cout << "Conditon Number Matrix " << test.matrix_cn(A) << endl;
	cout << "Conditon Number function " << test.func_cn(2) << endl;//s/b 3

}
void choleskyTest(){
	Matrix A(3,3);
	A(0,0)=5; A(0,1)=2; A(0,2)=1;
	A(1,0)=2; A(1,1)=8; A(1,2)=2;
	A(2,0)=1; A(2,1)=2; A(2,2)=8;
	
	cout << "Cholesky "<< cholesky(A) << endl;
	//cout << cholesky(A);
}
void positiveDefinite(){
	Matrix A(2,2), B(2,2);

	A(0,0)=5; A(0,1)=2;
	A(1,0)=2; A(1,1)=4;

	B(0,0)=5; B(0,1)=2;
	B(1,0)=2; B(1,1)=-4;
	cout << "Is Positive Definite Matrix " << is_positive_definite(A) << endl;
	cout << "Is Not Positive Definite Matrix " << is_positive_definite(B) << endl;
}
void markowtizTest(){
	//exampled commented in numeric.py
	Matrix A(3,3), mu(3,1);
	double rf = .05;
	
	A(0,0)=.04; A(0,1)=.006; A(0,2)=.02;
	A(1,0)=.006; A(1,1)=.09; A(1,2)=.06;
	A(2,0)=.02; A(2,1)=.06; A(2,2)=.16;

	mu(0,0)=.1;
	mu(1,0)=.12;
	mu(2,0)=.15;

	Markowitz test;

	test.compute_markowitz(mu,A,rf);

	cout << "Markowitiz: "  << endl;
	cout << "Optimized Portfolio Weights " << test.optimized_portfolio_wts() << endl;
	cout << "Portfolio Return "<< test.optimized_portfolio_rtn() << endl;
	cout << "Portfolio Risk "<< test.optimized_portfolio_risk() << endl;

}